﻿using LinearAlgebra.VectorAlgebra;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace NeuralNetwork
{
    public class Data
    {
        /// <summary>
        /// 真实值
        /// </summary>
        public int trueValueIndex;
        /// <summary>
        /// 真实值，如果真实值是5，则这里的是[0,0,0,0,0,1,0,0,0,0]，给神经网络计算误差的
        /// </summary>
        public Vector TrueValue;
        /// <summary>
        /// 像素灰度数据
        /// </summary>
        public Vector PixelValue;
    }
    /// <summary>
    /// 神经网络使用的数据的读取类
    /// </summary>
    public class DataSet
    {
        /// <summary>
        /// 训练集文件路径
        /// </summary>
        public string TrainSetPath { get; private set; }
        /// <summary>
        /// 测试集文件路径
        /// </summary>
        public string TestSetPath { get; private set; }

        /// <summary>
        /// 训练集
        /// </summary>
        public Data[] TrainSet;
        /// <summary>
        /// 测试集
        /// </summary>
        public Data[] TestSet;

        public bool done { get; private set; }

        public DataSet(string trainSetPath, string testSetPath)
        {
            TrainSetPath = trainSetPath;
            TestSetPath = testSetPath;
        }

        /// <summary>
        /// 准备数据
        /// </summary>
        public async Task PraperSet()
        {
            TrainSet = await LoadSet2Data(TrainSetPath);
            TestSet = await LoadSet2Data(TestSetPath);
            done = true;
        }
        /// <summary>
        /// 把路径下的文件转换为给神经网络使用的向量数据
        /// </summary>
        public async Task<Data[]> LoadSet2Data(string path)
        {
            var lines = await LoadSet2Strings(path);
            return await Task.Run(() =>
            {
                List<Data> dataList = new List<Data>();

                //foreach (var item in lines)
                for (int i = 0; i < lines.Length; i++)
                {
                    if (lines[i].Length < 1) continue;

                    var vals = lines[i].Split(',');
                    Data data = new Data();
                    //data.TrueValue = new Vector(VectorType.Column, int.Parse(vals[0]));
                    data.TrueValue = Vector.Zero(10, VectorType.Column);
                    data.trueValueIndex = int.Parse(vals[0]);
                    data.TrueValue[data.trueValueIndex] = 1;

                    string[] pixelStr = new string[vals.Length - 1];
                    Array.Copy(vals, 1, pixelStr, 0, pixelStr.Length);
                    data.PixelValue = new Vector(Array.ConvertAll(pixelStr, s => (double.Parse(s)+1)/256.0), VectorType.Column);// 这里+1是避免出现灰度值为0的情况
                    dataList.Add(data);

                    Console.WriteLine("Loading Data From {0} -> [{1}/{2}]", path, i+1, lines.Length);
                }

                return dataList.ToArray();
            });
        }
        /// <summary>
        /// 读取某路径下面的文本
        /// </summary>
        private async Task<string[]> LoadSet2Strings(string path)
        {
            if (!File.Exists(path))
            {
                Console.WriteLine("找不到文件：" + path);
                return new string[] { };
            }

            string[] lines = await Task.Run(() =>
            {
                return File.ReadAllLines(path);
            });

            return lines;
        }
    }
}
